package com.tianji.learning.service.impl;

import cn.hutool.core.io.unit.DataUnit;
import cn.hutool.db.Db;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.IdAndNumDTO;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.trade.OrderBasicDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.domain.query.PageQuery;
import com.tianji.common.enums.BaseEnum;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.*;
import com.tianji.learning.domain.dto.LearningPlanDTO;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.domain.vo.LearningLessonVO;
import com.tianji.learning.domain.vo.LearningPlanPageVO;
import com.tianji.learning.domain.vo.LearningPlanVO;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.PlanStatus;
import com.tianji.learning.mapper.LearningLessonMapper;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.service.ILearningRecordService;
import io.swagger.models.auth.In;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 学生课程表 服务实现类
 * </p>
 *
 * @author yp
 * @since 2024-07-19
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class LearningLessonServiceImpl extends ServiceImpl<LearningLessonMapper, LearningLesson> implements ILearningLessonService {

    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    //报错循环依赖 A 注入 B , B 注入A
//    private final ILearningRecordService learningRecordService;

    private final LearningRecordMapper recordMapper;

    /**
     * 添加课程到课表
     *
     * @param dto
     */
    @Override
    @Transactional
    public void addLesson(OrderBasicDTO dto) {
        //1.远程调用tj-course微服务，根据课程id查询课程信息（课程有效期）
        List<CourseSimpleInfoDTO> simpleInfoList = courseClient.getSimpleInfoList(dto.getCourseIds());
        if (CollUtils.isEmpty(simpleInfoList)) {
            throw new DbException("课程数据不存在");
        }
        //唯一标识 订单id
        //判断redis里面是否有当前的订单id ， 如果有不在调用业务了


        //2.遍历课程信息，封装LearningLesson(用户id,课程id,过期时间)，放到List<LearningLesson>
        List<LearningLesson> lessonList = new ArrayList<>();
        for (CourseSimpleInfoDTO course : simpleInfoList) {
            LearningLesson lesson = new LearningLesson();
            Integer validDuration = course.getValidDuration();
            if (validDuration != null && validDuration > 0) {
                lesson.setUserId(dto.getUserId());
                lesson.setCourseId(course.getId());
                lesson.setCreateTime(LocalDateTime.now());
                lesson.setExpireTime(LocalDateTime.now().plusMonths(validDuration));

            }
            lessonList.add(lesson);
        }
        //3.批量保存到数据库
        boolean success = saveBatch(lessonList);
        log.info("成功{}", success);
        if (!success) {
            throw new DbException("新增课程失败");
        }
        //把订单id存在redis里面去 ，保存60s


    }

    /**
     * 分页查询我的课表
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<LearningLessonVO> queeyMylessons(PageQuery query) {
        //1.分页查询当前用户的课表信息（获取当前用户的id）
        Long userId = UserContext.getUser();
        Page<LearningLesson> page = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<LearningLesson> lessonList = page.getRecords();
        if (CollUtils.isEmpty(lessonList)) {
            return PageDTO.empty(page);
        }
        //2 根据courseID查询出课表的信息
        List<Long> courseIds = lessonList.stream().map(LearningLesson::getCourseId).collect(Collectors.toList());
        //2.1全部课程
        List<CourseSimpleInfoDTO> courseList = courseClient.getSimpleInfoList(courseIds);
        if (CollUtils.isEmpty(courseIds)) {
            throw new DbException("课程信息不存在");
        }

        // courseList 转为 map， key是课程id 值value就是可成对象
        Map<Long, CourseSimpleInfoDTO> courseMap = courseList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));
        List<LearningLessonVO> volist = new ArrayList<>();
        //3.遍历课表list，每次遍历一次，就要封装LearningLessonVO
        for (LearningLesson lesson : lessonList) {
            LearningLessonVO vo = BeanUtils.copyBean(lesson, LearningLessonVO.class);
            //封装课程数据
            CourseSimpleInfoDTO course = courseMap.get(lesson.getCourseId());
            if (course != null) {
                vo.setCourseName(course.getName());
                vo.setCourseCoverUrl(course.getCoverUrl());
                vo.setSections(course.getSectionNum());
            }
            volist.add(vo);
        }
        //4.封装PageDTO
        return PageDTO.of(page, volist);
    }

    @Override
    public LearningLessonVO querycurrent() {
        //1.查询最近学习的课程（一门）select *from learning_lesson where user_id =2 AND status = 1 ORDER BY latest_learn_time DESC limit 0,1;
        Long userId = UserContext.getUser();
        LearningLesson lesson = getBaseMapper().queryCurrent(userId);
        if (lesson == null) {
            return null;
        }
        LearningLessonVO vo = BeanUtils.copyBean(lesson, LearningLessonVO.class);
        //2.根据课程id查询课程信息（远程调用）
        CourseFullInfoDTO course = courseClient.getCourseInfoById(lesson.getCourseId(), false, false);
        if (course == null) {
            throw new DbException("课程信息不存在");
        }
        vo.setCourseName(course.getName());
        vo.setCourseCoverUrl(course.getCoverUrl());
        vo.setSections(course.getSectionNum());
        //3.统计课表中课程的数量 courseAmout select COUNT(*) from Learning_lesson WHERE user_id =2
        Integer courseAmount = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .count();
        vo.setCourseAmount(courseAmount);

        Long latestSectionId = lesson.getLatestSectionId();
        if (latestSectionId != null && latestSectionId != 0) {
            //4.根据最近一次学习的小节查询小节的信息（远程调用）
            List<CataSimpleInfoDTO> cataList = catalogueClient.batchQueryCatalogue(List.of(lesson.getLatestSectionId()));
            if (CollUtils.isNotEmpty(cataList)) {
                CataSimpleInfoDTO cata = cataList.get(0);
                if (cata != null) {
                    vo.setLatestSectionName(cata.getName());
                    vo.setLatestSectionIndex(cata.getCIndex());
                }
            }
        }
        return vo;
    }

    @Override
    public LearningLessonVO queryByCourseId(Long courseId) {
        //1.根据用户id和课程id查询课表的LearningLesson
        LearningLesson lesson = lambdaQuery()
                .eq(LearningLesson::getCourseId, courseId)
                .eq(LearningLesson::getUserId, UserContext.getUser())
                .one();
        //2.根据课程id查询出课程信息
        if (lesson == null) {
            return null;
        }
        CourseFullInfoDTO course = courseClient.getCourseInfoById(lesson.getCourseId(), false, false);
        if (course == null) {
            throw new DbException("课程信息不存在");
        }
        //3.封装vo
        LearningLessonVO vo = BeanUtils.copyBean(lesson, LearningLessonVO.class);
        vo.setCourseName(course.getName());
        vo.setCourseCoverUrl(course.getCoverUrl());
        vo.setSections(course.getSectionNum());
        return vo;
    }

    @Override
    public Long judgecoureseisLessonValid(Long courseId) {
        LearningLesson lesson = lambdaQuery()
                .eq(LearningLesson::getCourseId, courseId)
                .eq(LearningLesson::getUserId, UserContext.getUser())
                .one();
        LocalDateTime now = LocalDateTime.now();
        //判断lesson是否为空 或者 大于过期时间；
        if (lesson == null || lesson.getExpireTime().isBefore(now)) {
            return null;
        }
        //取得课表id
        return lesson.getId();
    }

    /**
     * 删除课表中的课程
     *
     * @param courseId
     */
    @Override
    public void deletebyCouresId(Long courseId) {
        LearningLesson lesson = lambdaQuery()
                .eq(LearningLesson::getCourseId, courseId)
                .eq(LearningLesson::getUserId, UserContext.getUser())
                .one();

        if (lesson != null && lesson.getStatus() == LessonStatus.EXPIRED) {
            getBaseMapper().deleteById(lesson.getId());
        }
    }

    /**
     * 当退款成功的时候自动退课
     *
     * @param dto
     */
    @Override
    public void deletedtos(OrderBasicDTO dto) {
        Long userId = dto.getUserId();
        List<Long> courseIds = dto.getCourseIds();
        List<Long> ids = new ArrayList<>();
        if (userId != null && CollUtils.isNotEmpty(courseIds)) {
            for (Long courseId : courseIds) {
                LearningLesson lesson = lambdaQuery()
                        .eq(LearningLesson::getCourseId, courseId)
                        .eq(LearningLesson::getUserId, userId)
                        .one();
                if (lesson != null) {
                    ids.add(lesson.getId());
                }
            }
            getBaseMapper().deleteBatchIds(ids);
        }
    }


    /**
     * 统计课程学习人数
     *
     * @param courseId
     * @return
     */
    @Override
    public Integer countPeople(Long courseId) {
        return getBaseMapper().selectcourseSum(courseId);
    }

    /**
     * 需要返回课程的学习进度、课程有效期等信息
     *
     * @param courseId
     * @return
     */
    @Override
    public LearningLessonVO selectBycourseId(Long courseId) {
        return null;
    }

    /**
     * 创建我的学习计划
     *
     * @param dto
     */
    @Override
    @Transactional
    public void createLessonPlan(LearningPlanDTO dto) {
        //1.根据用户Userid和courseId查询出课表信息
        LearningLesson lesson = lambdaQuery()
                .eq(LearningLesson::getUserId, UserContext.getUser())
                .eq(LearningLesson::getCourseId, dto.getCourseId())
                .one();
        if (lesson == null) {
            throw new DbException("课表信息不存在");
        }
        //更新weekFrep,plan_status;
        LearningLesson lesson1 = new LearningLesson();
        lesson1.setId(lesson.getId());
        lesson1.setWeekFreq(dto.getFreq());
        if (lesson.getPlanStatus() == PlanStatus.NO_PLAN) {
            lesson1.setPlanStatus(PlanStatus.PLAN_RUNNING);
        }
        updateById(lesson1);
    }

    /**
     * 查询我的学习方法
     *
     * @param pageQuery
     * @return
     */
    @Override
    public LearningPlanPageVO queeyMypalns(PageQuery pageQuery) {
        LearningPlanPageVO vo = new LearningPlanPageVO();
        //1.查询本周的开始时间和结束时间
        LocalDate now = LocalDate.now();
        LocalDateTime weekBeginTime = DateUtils.getWeekBeginTime(now);
        LocalDateTime weekEndTime = DateUtils.getWeekEndTime(now);
        //2.获得用户id
        Long userId = UserContext.getUser();
        //3.查询当前用户的周计划
        //3.1查询当前用户已经学完的小节总数\
        //  SELECT count(*)
        //	from learning_record
        //	WHERE user_id = 2
        //  and finish_time > "2021-10-10 00:00:00"
        //	and finish_time < "2023-10-10 23:00:00"
        //	and finished = 1;

        Integer integer = recordMapper.selectCount(
                new LambdaQueryWrapper<LearningRecord>()
                        .eq(LearningRecord::getFinished, true)
                        .gt(LearningRecord::getFinishTime, weekBeginTime)
                        .lt(LearningRecord::getFinishTime, weekEndTime)
                        .eq(LearningRecord::getUserId, userId)
        );
        vo.setWeekFinished(integer);
        //3.2查询当前周本周计划学习小节的总数
//        SELECT sum(week_freq) from learning_lesson WHERE user_id = 2 and plan_status =1 and `status` in (0,1)
        Integer weekTotalplan = getBaseMapper().queryWeekTotalPlan(userId);
        vo.setWeekTotalPlan(weekTotalplan);
        //4.1分页查询查询用户列表的数据
//        -- 分页查询用户课表
//        SELECT * FROM learning_lesson WHERE user_id =129 and plan_status=1 and `status` in (0,1)    、
        Page<LearningLesson> page = lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getPlanStatus, 1)
                .in(LearningLesson::getStatus, LessonStatus.NOT_BEGIN, LessonStatus.LEARNING)
                .page(pageQuery.toMpPage("latest_learn_time", false));
        List<LearningLesson> lessonList = page.getRecords();
        if (CollUtils.isEmpty(lessonList)) {
            return vo.emptyPage(page);
        }
        //4.2根据coureceId查询课程信息
        List<Long> collect = lessonList.stream().map(LearningLesson::getCourseId).collect(Collectors.toList());
        List<CourseSimpleInfoDTO> courseLists = courseClient.getSimpleInfoList(collect);
        if (CollUtils.isEmpty(courseLists)) {
            throw new DbException("课程信息不存在");
        }

        Map<Long, CourseSimpleInfoDTO> courseMap = courseLists.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));

        //                -- 查询d当前用户某个课程本周的学习小节数
//        SELECT lesson_id , count(*) from learning_record WHERE user_id = 2 AND finished =1 and finish_time > "2021-10-10 00:00:00" and finish_time < "2028-10-10 23:00:00" GROUP BY lesson_id;
        List<IdAndNumDTO> idAndNumDTOS = recordMapper.countLearnedSections(weekBeginTime, weekEndTime, userId);
        Map<Long, Integer> idAndNumMap = IdAndNumDTO.toMap(idAndNumDTOS);
        //4.4 遍历课表list封装volist
        List<LearningPlanVO> voList = new ArrayList<>();
        for (LearningLesson lesson : lessonList) {
            //每遍历一次就要封装一个LearningPlanVO
            LearningPlanVO planVO = BeanUtils.copyBean(lesson, LearningPlanVO.class);
            //封装课程信息
            CourseSimpleInfoDTO course = courseMap.get(lesson.getCourseId());
            if (course != null) {
                planVO.setCourseName(course.getName());
                planVO.setSections(course.getSectionNum());
            }
            //封装已经学习的小节数据
            planVO.setWeekLearnedSections(idAndNumMap.getOrDefault(lesson.getId(), 0));
            voList.add(planVO);
        }

        return vo.pageInfo(page.getTotal(), page.getPages(), voList);
    }


}
